﻿namespace IBTrader.Modules.Tws
{
    using AxTWSLib;
using IBTrader.Model;
using IBTrader.Modules.Configuration;
using IBTrader.Modules.Market;
using IBTrader.Modules.Read;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

    class IBSimulator
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
        public event _DTwsEvents_orderStatusEventHandler orderStatus;
        public event _DTwsEvents_nextValidIdEventHandler nextValidId;
        private readonly IIB ib;
        private readonly Store store;
        private Line last;
        private static readonly OrderStatus[] end = new[] { OrderStatus.Filled, OrderStatus.Cancelled };
        public IBSimulator(IIB ib, Store store)
        {
            this.ib = ib;
            this.store = store;
        }
        public void Last(object _, Line line)
        {
            if (ib.IsConnected()) return;

            this.last = line;

            var order = store.Orders.LastOrDefault();
            if (order == null || end.Contains(order.Status)) return;

            if (order.Created + order.Algo.OrderDuration < line.DateTime)
            {
                if (orderStatus != null) orderStatus(this, new _DTwsEvents_orderStatusEvent(order.Id, OrderStatus.Cancelled.ToString(), 0, order.Quantity, 0, 0, 0, 0, 0, null));
            }
            else if (order.OrderType == OrderType.MKT)
            {
                if (orderStatus != null) orderStatus(this, new _DTwsEvents_orderStatusEvent(order.Id, OrderStatus.Filled.ToString(), order.Quantity, 0, line.Price, 0, 0, 0, 0, null));
            }
            else if ((order.Action == OrderAction.BUY && order.Price >= line.Price) || (order.Action == OrderAction.SELL && order.Price <= line.Price))
            {
                if (order.Algo.TradingCancelled)
                {
                    if (orderStatus != null) orderStatus(this, new _DTwsEvents_orderStatusEvent(order.Id, OrderStatus.Cancelled.ToString(), 0, order.Quantity, 0, 0, 0, 0, 0, null));
                }
                else
                {
                    var price = order.Algo.OptimisticSimulation ? line.Price : order.Price;
                    if (orderStatus != null) orderStatus(this, new _DTwsEvents_orderStatusEvent(order.Id, OrderStatus.Filled.ToString(), order.Quantity, 0, price, 0, 0, 0, 0, null));
                }
            }
        }
        public void End(object o, Line line)
        {
            if (last != null)
                Last(o, new Line { DateTime = line.DateTime, Price = last.Price });
            if (nextValidId != null)
                nextValidId(this, new _DTwsEvents_nextValidIdEvent(0));
        }
    }
}